package top.zsyle.sycc.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import io.seata.spring.annotation.GlobalTransactional;
import org.bouncycastle.jcajce.provider.asymmetric.util.PrimeCertaintyCalculator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import sun.security.util.AuthResources_it;
import top.zsyle.sycc.bo.VerifySmsCodeBo;
import top.zsyle.sycc.constants.VerifyCodeConstant;
import top.zsyle.sycc.domain.Login;
import top.zsyle.sycc.domain.User;
import top.zsyle.sycc.domain.UserAccount;
import top.zsyle.sycc.domain.UserBaseInfo;
import top.zsyle.sycc.dto.RegisterPhoneDto;
import top.zsyle.sycc.exception.GlobalExceptionEnum;
import top.zsyle.sycc.feign.LoginService;
import top.zsyle.sycc.mapper.UserMapper;
import top.zsyle.sycc.result.JsonResult;
import top.zsyle.sycc.service.IUserAccountService;
import top.zsyle.sycc.service.IUserBaseInfoService;
import top.zsyle.sycc.service.IUserService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import top.zsyle.sycc.utils.AssertUtil;
import top.zsyle.sycc.utils.BitStatesUtils;

import javax.xml.crypto.Data;
import java.util.Date;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author zhongshiyi
 * @since 2022-12-27
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private LoginService loginService;

    @Autowired
    private IUserAccountService userAccountService;

    @Autowired
    private IUserBaseInfoService userBaseInfoService;

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void registerByPhone(RegisterPhoneDto dto) {
        String mobile = dto.getMobile();
        String smsCode = dto.getSmsCode();
        //1.校验参数
        //2.校验短信验证码
        String redisKey = String.format(VerifyCodeConstant.REDIS_REGISTER_PHONE, mobile);
        Object o = redisTemplate.opsForValue().get(redisKey);
        AssertUtil.isNotNull(o, GlobalExceptionEnum.USER_PHONE_CODE_IS_OVERTIME_EXCEPTION);
        VerifySmsCodeBo verifySmsCodeBo = (VerifySmsCodeBo) o;
        AssertUtil.isEqualsIgnoreCase(verifySmsCodeBo.getCode(), smsCode, GlobalExceptionEnum.USER_CODE_IS_UNEQUAL_EXCEPTION);
        //2.查找电话号码是否已经注册
        selectByPhone(mobile);
        //3.开始注册，t_login,t_user,t_user_account
        //使用feign调用user服务
        Long loginId = saveLogin(dto);

        //4.保存user
        Long userId = saveUser(dto, loginId);
        //5.保存t_user_account
        saveUserAccount(dto,userId);
        //6.保存t_user_base_info
        saveUserBaseInfo(dto,userId);
    }

    private void saveUserBaseInfo(RegisterPhoneDto dto,Long userId) {
        UserBaseInfo userBaseInfo = new UserBaseInfo();
        userBaseInfo.setCreateTime(new Date().getTime());
        userBaseInfo.setRegChannel(dto.getRegChannel());
        userBaseInfo.setId(userId);
        userBaseInfoService.insert(userBaseInfo);
    }

    private void saveUserAccount(RegisterPhoneDto dto,Long userId) {
        UserAccount userAccount = new UserAccount();
        userAccount.setCreateTime(new Date().getTime());
        userAccount.setPassword(dto.getPassword());
        userAccount.setId(userId);
        userAccountService.insert(userAccount);
    }

    private Long saveUser(RegisterPhoneDto dto, Long loginId) {
        User user = new User();
        user.setCreateTime(new Date().getTime());
        user.setPhone(dto.getMobile());
        user.setNickName(dto.getMobile());
        user.setLoginId(loginId);
        long bitState = BitStatesUtils.addState(BitStatesUtils.OP_REGISTED, BitStatesUtils.OP_ACTIVED);
        bitState = BitStatesUtils.addState(bitState,BitStatesUtils.OP_AUTHED_PHONE);
        user.setBitState(bitState);
        insert(user);
        return user.getId();
    }

    private Long saveLogin(RegisterPhoneDto dto) {
        Login login = new Login();
        login.setUsername(dto.getMobile());
        login.setPassword(dto.getPassword());
        login.setType(Login.HOME_TYPE);
        login.setEnabled(Login.ENABLE_OPEN);
        login.setAccountNonExpired(Login.ACCOUNT_NON_EXPIRED);
        login.setCredentialsNonExpired(Login.CREDENTIALS_NON_EXPIRED);
        login.setAccountNonLocked(Login.ACCOUNT_NON_LOCKED);
        //如果login添加失败  是否接收到熔断数据
        JsonResult jsonResult = loginService.saveOrUpdate(login);
        AssertUtil.isTrue(jsonResult.isSuccess(), GlobalExceptionEnum.ERROR);
        //判断数据是否接收到了
        AssertUtil.isNotNull(jsonResult.getData(), GlobalExceptionEnum.ERROR);
        return Long.valueOf(jsonResult.getData().toString());
    }

    //查找电话号码是否已经注册
    private void selectByPhone(String mobile) {
        Wrapper<User> wrapper = new EntityWrapper<>();
        wrapper.eq("phone", mobile);
        User user = selectOne(wrapper);
        AssertUtil.isNull(user, GlobalExceptionEnum.USER_PHONE_IS_EXIST_EXCEPTION);

    }
}
